<?php
/* 快速排序  */
function quick_sort($array){
	$len = count($array);
	if($len <= 1)
		return $array;
	
	$left_array = array();
	$right_array = array();
	$key = $array[0];
	for($i=1; $i<$len; $i++){
		if($key < $array[$i]){
			$right_array[] = $array[$i];
		}else{
			$left_array[]=$array[$i];
		}
		$first_array = array_merge($left_array, array($key), $right_array);
	}
	return $first_array;
}
//记录排序
function sort_record($data,$key){
	$rs= array();
	for($i=0;$i<count($data);$i++){
		$f = $i;
		for($j=$i+1;$j<=count($data);$j++){
			if( $data[$j][$key] > $data[$i][$key])
				$f = $j;
		}
		$rs[] = $data[$f];
	}
	
	return $rs;
}
//二维数组中，某一个数组中，某一项中，最大的值
function getArrMax($arr , $f){
	$tmp = 0;
	foreach($arr as $k=>$v){
		if($v[$f] > $tmp)$tmp = $v[$f];
	}
	return $tmp;
}
//取得<周>相关信息
function get_week_info($gdate = ""){ 
	if(!$gdate) $gdate = date("Y-m-d");
	$w = date("w", strtotime($gdate));//取得一周的第几天,星期天开始0-6
	$dn = $w - 1;
// 	if(!$dn)$dn = 6;
	//本周开始日期
	$st = date("Y-m-d", strtotime("$gdate -".$dn." days"));
	//本周结束日期
	$en = date("Y-m-d", strtotime("$st +6 days"));
	//上周开始日期
	$last_st = date('Y-m-d',strtotime("$st - 7 days"));
	//上周结束日期
	$last_en = date('Y-m-d',strtotime("$st - 1 days"));
	return array('start_date'=>$st,'end_date'=> $en,'last_start_date'=> $last_st,'last_end_date'=>$last_en);//返回开始和结束日期
}
//获取一个月的最后一天
function get_month_last_day($year,$month){
	if(substr($month,0,1) === 0)
		$month = substr($month,1,1);
	
	$rs = 0;
	switch ($month){
		case 1:
			$rs = 31;break;
		case 2:
			if($year % 4 == 0)
				$rs = 28;
			else
				$rs = 29;
			break;
		case 3:
			$rs = 31;break;
		case 4:
			$rs = 30;break;
		case 5:
			$rs = 31;break;
		case 6:
			$rs = 30;break;
		case 7:
			$rs = 31;break;
		case 8:
			$rs = 31;break;
		case 9:
			$rs = 30;break;
		case 10:
			$rs = 31;break;
		case 11:
			$rs = 30;break;
		case 12:
			$rs = 31;break;
		default:
			
	}
	
	return $rs;
}
//取得当<月>相关信息
function get_month_info($gdate = ""){
	if(!$gdate) $gdate = date("Y-m-d");
}
//判断某一个值，是否在数据中
function arr_in_arr($arr,$key,$node){
	$f = 0;
	foreach($arr as $k=>$v){
		if($node  == $v[$key]){
			$f = 1;
			break;
		}
	}

	return $f;
}
//把一个数组中的KEY值，转换成一个数组
function key_turn_arr($arr){
	$rs = array();
	foreach($arr as $k=>$v){
		$rs[] = $k;
	}
	return $rs;
}
//将一个数组中的某个键值，组成成一个字符串：1,3,2,2,2
function split_arr($arr,$keyName = ''){
	$str = "";
	if(!$keyName){
		foreach($arr as $k=>$v){
			$str .= $v . ","; 
		}
	}else{
		foreach($arr as $k=>$v){
			$str .= $v[$keyName] . ","; 
		}
	}
	return substr($str, 0 , strlen($str) - 1);
}
//将一个数组中的某个键值，组成成一个字符串：1,3,2,2,2
function split_arr_one($arr){
	$rs = "";
	foreach($arr as $k=>$v){
		$rs .= $v . ",";
	}
	return substr($rs, 0 , strlen($rs) - 1);
}
//将一个数组中的某个键值，组成成一个字符串：1,3,2,2,2
function split_arr_sql($arr,$keyName = ''){
	$str = "";
	if(!$keyName){
		foreach($arr as $k=>$v){
			$str .= "'" . $v . "',";
		}
	}else{
		foreach($arr as $k=>$v){
			$str .= "'" .$v[$keyName] . "',";
		}
	}
	return substr($str, 0 , strlen($str) - 1);
}
//array('name'=>'lisi',id=1)转换成    array(id=>'lisi')
function two_turn_one($arr,$key,$val){
	$rs = array();
	foreach($arr as $k=>$v){
		$rs[$v[$key]] = $v[$val];
	}
	
	return $rs;
}

// function authIp(){
// 	$IP = get_client_ip();
// 	$db = getDb('local_pbm');
// 	$disable_ip = $this->db->getTableAll('disable_ip');
// 	if(!$disable_ip)return true;
// 	$disable_ip = somearr_to_onearr($disable_ip);
// 	if(in_array($IP, $disable_ip))stop('IP禁止访问');
// }
//
//将array('t'=>222,'t2'=>33)转成数字键值(0=>222,1=>33)
function somearr_to_onearr($somearr){
	$rs = array();
	foreach($somearr as $k=>$v){
		$rs[] = $v;
	}
	
	return $rs;
}
//抛出异常
function stop($error,$module = '',$back_url = ''){
	ExceptionFrameLib::halt($error , $module  , $back_url);
}
// PHP_SELF:当前所执行的脚本的文件名，如:b.com/test/test.php?k=v，则PHP_SELF的值为/test/test.php。
// SCRIPT_NAME：当前执行的脚本的路径，如:B.com/test/test.php?k=v，则SCRIPT_NAME的值为/test/test.php。
// SCRIPT_FILENAME：前执行的脚本的绝对路径，如:B.com/test/test.php?k=v，值 为/var/www/test/test.php。注：相对路径，CLI方式来执行，例如../test/test.php，即../test/test.php。
// PATH_INFO：客户端提供的路径信息，即在实际执行脚本后面尾随的内容，但是会去掉query string。如:b.com/test/test.php/a/b?k=v，则PATH_INFO的值为/a/bREQUEST_URI：包含HTTP协议中定义的URI内容。如果请求http://example.com/test/test.php?k=v，则REQUEST_URI为/test/test.php?k=v
// PHP_SELF和SCRIPT_NAME区别：b.com/test/test.php/a/b?k=v候，PHP_SELF为/test/test.php/a/b，SCRIPT_NAME为/test/test.php，可以看出PHP_SELF比SCRIPT_NAME多了PATH_INFO的内容。
//发现了一件很好玩的事情，WIN下，有个文件叫：admin.php,如果在地址栏里输入大写的：ADMIN.PHP,也是能执行的，而此时，$_SERVER['SCRIPT_FILENAME']的结果就是小写的：admin.php
function _get_script_url() {
	$rs = "";
	$scriptName = basename($_SERVER['SCRIPT_FILENAME']);
	if(basename($_SERVER['SCRIPT_NAME']) === $scriptName) {
		$rs = $_SERVER['SCRIPT_NAME'];
	}else if(basename($_SERVER['PHP_SELF']) === $scriptName) {
		$rs = $_SERVER['PHP_SELF'];
	} else if(($pos = strpos($_SERVER['PHP_SELF'],'/'.$scriptName)) !== false) {
		$rs = substr($_SERVER['SCRIPT_NAME'],0,$pos).'/'.$scriptName;
	}else{
		stop('文件名错误');
	}
	return $rs;
}
//seo robot 文件
function checkrobot($useragent = '') {
	static $kw_spiders = array('bot', 'crawl', 'spider' ,'slurp', 'sohu-search', 'lycos', 'robozilla');
	static $kw_browsers = array('msie', 'netscape', 'opera', 'konqueror', 'mozilla');

	$useragent = strtolower(empty($useragent) ? $_SERVER['HTTP_USER_AGENT'] : $useragent);
	if(strpos($useragent, 'http://') === false && dstrpos($useragent, $kw_browsers)) return false;
	if(dstrpos($useragent, $kw_spiders)) return true;
	return false;
}

function return_bytes($val) {
	$val = trim($val);
	$last = strtolower($val{strlen($val)-1});
	switch($last) {
		case 'g': $val *= 1024;
		case 'm': $val *= 1024;
		case 'k': $val *= 1024;
	}
	return $val;
}


//取得文件扩展名
function get_file_ext($path){
	$length = strlen($path);
	$l = "";
	for($i=$length-1;$i>=0;$i--){
		$str = substr($path, $i,1);
		if($str == '.'){
			$l = $i;
			break;
		}
	}
	$rs = substr($path, $l+1);
	return $rs;
}
function __autoload($class){
	if( strpos($class,M_CLASS) !== false){
		
		$l = strpos($class,M_CLASS);
		$class = strtolower(substr($class, 0,$l));
		
		include_once $class .M_EXT;
	}elseif( strpos($class,C_CLASS) !== false){
		
		$l = strpos($class,C_CLASS);
		$class = substr($class, 0,$l);
		
		include_once strtolower($class .C_EXT);
	}elseif( strpos($class,LIB_CLASS) !== false){
		
		$l = strpos($class,LIB_CLASS);
		$class = substr($class, 0,$l);
		
		include_once $class .LIB_EXT;
	}
}
// 取得对象实例 支持调用类的静态方法
function get_instance_of($name, $method='', $args=array()) {
	static $_instance = array();
// 	$identify = empty($args) ? $name . $method : $name . $method . to_guid_string($args);
	if ( ! isset($_instance[$name]) ) {
		if (class_exists($name)) {
			$o = new $name();
			$_instance[$name] = $o;
// 			if (method_exists($o, $method)) {
// 				if (!empty($args)) {
// 					$_instance[$name] = call_user_func_array(array(&$o, $method), $args);
// 				} else {
// 					$_instance[$name] = $o->$method();
// 				}
// 			}else{
// 				$_instance[$name] = $o;
// 			}
// 		}else{
// 			stop("new class:". $name);
		}else stop("class not exists:". $name,1,1);
	}
	return $_instance[$name];
}
// 获取配置值
function C($name=null, $value=null) {
	static $_config = array();
	// 无参数时获取所有
	if (empty($name))   return $_config;
	// 优先执行设置获取或赋值
	if (is_string($name)) {
		if (!strpos($name, '.')) {
			$name = strtolower($name);
			if (is_null($value))
				return isset($_config[$name]) ? $_config[$name] : null;
			$_config[$name] = $value;
			return;
		}
		// 二维数组设置和获取支持
		$name = explode('.', $name);
		$name[0]   =  strtolower($name[0]);
		if (is_null($value))
			return isset($_config[$name[0]][$name[1]]) ? $_config[$name[0]][$name[1]] : null;
		$_config[$name[0]][$name[1]] = $value;
		return;
	}
	// 批量设置
	if (is_array($name)){
		return $_config = array_merge($_config, array_change_key_case($name));
	}
	return null; // 避免非法参数
}
function ajax_stop($msg){
	$js = array('err'=>1,'msg'=>$msg,'data'=>'');
	echo json_encode($js);
	exit;
}
// 获取客户端IP地址
function get_client_ip() {
	static $ip = NULL;
	if ($ip !== NULL) return $ip;
	if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
		$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
		$pos =  array_search('unknown',$arr);
		if(false !== $pos) unset($arr[$pos]);
		$ip   =  trim($arr[0]);
	}elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
		$ip = $_SERVER['HTTP_CLIENT_IP'];
	}elseif (isset($_SERVER['REMOTE_ADDR'])) {
		$ip = $_SERVER['REMOTE_ADDR'];
	}
	// IP地址合法验证
	$ip = (false !== ip2long($ip)) ? $ip : '0.0.0.0';
	return $ip;
}
//判断长度
function slen($value,$max,$min = 1,$unicode = 'utf8'){
	$str = mb_strlen($value , $unicode);
	if( $str > $max || $str < $min){
		return 0;
	}
	
	return 1;
}
//GET POST REQUEST
function _g($name, $type = '' , $is_null = 0) {
	if (isset($_POST[$name]))   $ret = $_POST[$name];
	elseif (isset($_GET[$name]))   $ret = $_GET[$name];
	elseif (isset($_REQUEST[$name]))   $ret = $_REQUEST[$name];
	else {
		$ret = false;
		if($is_null)
			stop($name.':参数格式错误-空');
		
	}
	
	if(!$ret)
		if($is_null)
			stop($name.':参数格式错误-空');
		
	if(!is_array($ret)){
		$ret = trim($ret);         		//清理空格字符
		$ret = nl2br($ret);         	//将换行符转化为<br />
		$ret = strip_tags($ret);      	//过滤文本中的HTML标签
		$ret = htmlspecialchars($ret); 	//将文本中的内容转换为HTML实体
		$ret = addslashes($ret);      	//加入字符转义
	}
	
	
	if ($ret && $type != '') {
		if(!in_array($type,array_flip(FilterLib::$validate)))
			stop('type kery错误'.$type,'G_PARA');
			
		if(!FilterLib::regex($ret,$type))
			stop('数据类型错误'.$type,'G_PARA');
	}
	return $ret;
}
//发送HTTP状态
function send_http_status($code) {
	static $_status = array(
	// Success 2xx
			200 => 'OK',
			// Redirection 3xx
			301 => 'Moved Permanently',
			302 => 'Moved Temporarily ',  // 1.1
			// Client Error 4xx
			400 => 'Bad Request',
			403 => 'Forbidden',
			404 => 'Not Found',
			// Server Error 5xx
			500 => 'Internal Server Error',
			503 => 'Service Unavailable',
	);
	if(isset($_status[$code])) {
		header('HTTP/1.1 '.$code.' '.$_status[$code]);
		// 确保FastCGI模式下正常
		header('Status:'.$code.' '.$_status[$code]);
	}
}
//取得SMARTY实例
function getSmartyObject($path = ''){
	$Template = get_instance_of('TemplateLib');
	
	if(!$path){
		$Template->setPath(BASE_DIR."/view/");
		$Template->setCompilePath( BASE_DIR."/view_c/");
	}else{
		$Template->setPath($path."/view/");
		$Template->setCompilePath( $path."/view_c/");
	}
	
	return $Template;
}

function setSmartyPath($path){
	$SmartyClass = get_instance_of('Smarty');
	$SmartyClass->setTemplateDir($path);
}

//判断是否有权限
function file_mode_info($file_path)
{
    /* 如果不存在，则不可读、不可写、不可改 */
    if (!file_exists($file_path))
    {
        return false;
    }
    $mark = 0;
    if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN')
    {
        /* 测试文件 */
        $test_file = $file_path . '/cf_test.txt';
        /* 如果是目录 */
        if (is_dir($file_path))
        {
            /* 检查目录是否可读 */
            $dir = @opendir($file_path);
            if ($dir === false)
            {
                return $mark; //如果目录打开失败，直接返回目录不可修改、不可写、不可读
            }
            if (@readdir($dir) !== false)
            {
                $mark ^= 1; //目录可读 001，目录不可读 000
            }
            @closedir($dir);
            /* 检查目录是否可写 */
            $fp = @fopen($test_file, 'wb');
            if ($fp === false)
            {
                return $mark; //如果目录中的文件创建失败，返回不可写。
            }
            if (@fwrite($fp, 'directory access testing.') !== false)
            {
                $mark ^= 2; //目录可写可读011，目录可写不可读 010
            }

            @fclose($fp);
            @unlink($test_file);
            /* 检查目录是否可修改 */
            $fp = @fopen($test_file, 'ab+');
            if ($fp === false)
            {
                return $mark;
            }
            if (@fwrite($fp, "modify test.\r\n") !== false)
            {
                $mark ^= 4;
            }
            @fclose($fp);
            /* 检查目录下是否有执行rename()函数的权限 */
            if (@rename($test_file, $test_file) !== false)
            {
                $mark ^= 8;
            }
            @unlink($test_file);
        }
        /* 如果是文件 */
        elseif (is_file($file_path))
        {
            /* 以读方式打开 */
            $fp = @fopen($file_path, 'rb');
            if ($fp)
            {
                $mark ^= 1; //可读 001
            }
            @fclose($fp);
            /* 试着修改文件 */
            $fp = @fopen($file_path, 'ab+');
            if ($fp && @fwrite($fp, '') !== false)
            {
                $mark ^= 6; //可修改可写可读 111，不可修改可写可读011...
            }
            @fclose($fp);
            /* 检查目录下是否有执行rename()函数的权限 */
            if (@rename($test_file, $test_file) !== false)
            {
                $mark ^= 8;
            }
        }
    }
    else
    {
        if (@is_readable($file_path))
        {
            $mark ^= 1;
        }
        if (@is_writable($file_path))
        {
            $mark ^= 14;
        }
    }
    return $mark;
}
//取得数据库实例
function getDb($dbName){
	static $dbLink = array();
	if(!isset($dbLink[$dbName])){
		foreach($GLOBALS['db_config'] as $k=>$v){
			if($k == $dbName){
				$f = 1;
				$config = $v;
			}
		}
		if(!$f){
			stop('DB_config error','no');
		}
		// 		include 'Model.class.php';
		$db = new DbLib($config);
		$dbLink[$dbName] =  $db;
	}
	return $dbLink[$dbName];
}
//单实例模式
// function Singleton ($className){
// 	static $_instens = array();
// 	if(!isset($_instens[$className])){
// 		$_instens[$className] = new $className;
// 	}
// 	return $_instens[$className];
// }
// 根据PHP各种类型变量生成唯一标识号
function to_guid_string($mix) {
	if (is_object($mix) && function_exists('spl_object_hash')) {
		return spl_object_hash($mix);
	} elseif (is_resource($mix)) {
		$mix = get_resource_type($mix) . strval($mix);
	} else {
		$mix = serialize($mix);
	}
	return md5($mix);
}
// 设置和获取统计数据
function N($key, $step=0) {
	static $_num = array();
	if (!isset($_num[$key])) {
		$_num[$key] = 0;
	}
	if (empty($step))
		return $_num[$key];
	else
		$_num[$key] = $_num[$key] + (int) $step;
}
// 记录和统计时间（微秒）
function G($start,$end='',$dec=4) {
	static $_info = array();
	if(is_float($end)) { // 记录时间
		$_info[$start]  =  $end;
	}elseif(!empty($end)){ // 统计时间
		if(!isset($_info[$end])) $_info[$end]   =  microtime(TRUE);
		return number_format(($_info[$end]-$_info[$start]),$dec);
	}else{ // 记录时间
		$_info[$start]  =  microtime(TRUE);
	}
}
// 显示运行时间
function showtime() {
	global $db_sql_cnt;
	$process_time = microtime(TRUE) - $GLOBALS['start_time'] ;
	$showTime   =   'Process: '.$process_time.'s ';
	// 显示数据库操作次数
	$showTime .= ' | DB_select :'.N('db_query').' ,DB_write '.N('db_write');
	// 显示内存开销
	$showTime .= ' | UseMem:'. number_format((memory_get_usage() - $GLOBALS['start_use_mems'])/1024).' kb';
	$showTime .= ' | LoadFile:'.count(get_included_files());
	$fun  =  get_defined_functions();
	$showTime .= ' | CallFun:'.count($fun['user']).','.count($fun['internal']);
	return $showTime;
}
//初始化的常量值，必埴项检查
function check_const(){
	if(!defined('PROJECT_PATH'))exit('常量未定义：PROJECT_PATH');
	if(!defined('KERNEL_PATH'))exit('常量未定义：:KERNEL_PATH');
	if(!defined('APP_NAME'))exit('常量未定义：APP_NAME');
	if(!defined('APP_PATH'))exit('常量未定义：APP_PATH');
	if(!defined('USER_TYPE'))exit('常量未定义：USER_TYPE');
	if(!defined('DOMAIN'))exit('常量未定义：DOMAIN');
	if(!defined('DOMAIN_KERNEL'))exit('常量未定义：DOMAIN_KERNEL');
	if(!defined('ERROR_TPL'))exit('常量未定义：ERROR_TPL');
	if(!defined('DEF_DB_CONN'))exit('常量未定义：DEF_DB_CONN');
}

function get_dir($directory){
	$rs = array();
	$mydir = dir($directory);
	while($file=$mydir->read()){
		if( $file!="." && $file!=".."){
			if( is_dir("$directory/$file")){
				$rs = get_dir("$directory/$file");
			}else{
				$rs[$directory][] = $file;
			}
		}
	}
	$mydir->close();
	return $rs;
}

